iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0

Div and Mod

integer 和 Decimals 遇到 // 和 % 運算子 (當然也包括 divmod() 函式) 的行為不大相同:

Decimals 的除法是 truncated division
integer 的除法是 floored division

這兩者的差異只有在運算負數時看得出來——重點是它們都要遵守之前提到這個公式

n = d * (n // d) + (n % d)

來看以下的例子:

import decimal
from decimal import Decimal
x = 10
y = 3
print(x//y, x%y)
print(divmod(x, y))
print( x == y * (x//y) + x % y)
3 1
(3, 1)
True
a = Decimal('10')
b = Decimal('3')
print(a//b, a%b)
print(divmod(a, b))
print( a == b * (a//b) + a % b)
3 1
(Decimal('3'), Decimal('1'))
True

可以發現,對於正數的 // 和 % 運算,兩者沒有差異。
但負數呢?

x = -10
y = 3
print(x//y, x%y)
print(divmod(x, y))
print( x == y * (x//y) + x % y)
-4 2
(-4, 2)
True
a = Decimal('-10')
b = Decimal('3')
print(a//b, a%b)
print(divmod(a, b))
print( a == b * (a//b) + a % b)
-3 -1
(Decimal('-3'), Decimal('-1'))
True

interger 和 Decimals 的運算結果不同,不過套進文章開頭提到的公式都會成立,Decimals 的結果看起來就像我們日常熟悉的商數和餘數運算。

其他 Mathematical Functions

Decimal 類別內建了很多數學運算函式:

a = Decimal('1.5')
print(a.log10())  # base 10 logarithm
print(a.ln())     # natural logarithm (base e)
print(a.exp())    # e**a
print(a.sqrt())   # square root
0.1760912590556812420812890085
0.4054651081081643819780131155
4.481689070338064822602055460
1.224744871391589049098642037

你也可以用 math 模組裡的函式對 Decimals 做運算, 不過要小心! 套用 math 模組裡的函式時,Decimals 會先被轉成 float 再運算,所以如果你很在乎精確度(用 Decimals 通常就是為了精確),就要小心這種操作反而會讓結果失真。

x = 2
x_dec = Decimal(2)
import math
root_float = math.sqrt(x)
root_mixed = math.sqrt(x_dec)
root_dec = x_dec.sqrt()
print(format(root_float, '1.27f'))
print(format(root_mixed, '1.27f'))
print(root_dec)
1.414213562373095145474621859
1.414213562373095145474621859
1.414213562373095048801688724
print(format(root_float * root_float, '1.27f'))
print(format(root_mixed * root_mixed, '1.27f'))
print(root_dec * root_dec)
2.000000000000000444089209850
2.000000000000000444089209850
1.999999999999999999999999999
x = 0.01
x_dec = Decimal('0.01')

root_float = math.sqrt(x)
root_mixed = math.sqrt(x_dec)
root_dec = x_dec.sqrt()

print(format(root_float, '1.27f'))
print(format(root_mixed, '1.27f'))
print(root_dec)
0.100000000000000005551115123
0.100000000000000005551115123
0.1
print(format(root_float * root_float, '1.27f'))
print(format(root_mixed * root_mixed, '1.27f'))
print(root_dec * root_dec)
0.010000000000000001942890293
0.010000000000000001942890293
0.01

可以看到上面例子,套用 Decimals 本身的 sqrt 方法可以算出精確的開根號結果;使用 math.sqrt 則反而有誤差。

好啦,我們明天見!

參考:Python 3: Deep Dive (Part 1 - Functional)


上一篇
Decimals: Constructors and Contexts
下一篇
Decimals: Performance 問題
系列文
小青蛇變大蟒蛇——進階Python學起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言